<?php
/**
 * 菜单控制器 - 处理菜单URL到API接口的映射
 * @middleware think\middleware\AllowCrossDomain
 */
declare (strict_types = 1);

namespace app\controller\home;

use app\BaseController;
use think\facade\Db;
use think\facade\Request;

class Menu extends BaseController
{
    /**
     * 不需要登录的方法
     * @var array
     */
    protected $noNeedLogin = ['updateMigSrc', 'getMenuTree', 'batchUpdateMigSrc', 'updateSingleMenuMigSrc'];
    
    /**
     * 不需要鉴权的方法
     * @var array
     */
    protected $noNeedRight = ['updateMigSrc', 'getMenuTree', 'batchUpdateMigSrc', 'updateSingleMenuMigSrc'];
    
    /**
     * 更新单个菜单的mig_src字段
     */
    public function updateSingleMenuMigSrc()
    {
        $param = Request::param();
        
        // 验证参数
        if (empty($param['id'])) {
            return json(['code' => 400, 'msg' => '菜单ID不能为空']);
        }
        
        try {
            // 查询菜单信息
            $menu = Db::name('admin_rule')
                ->where('id', $param['id'])
                ->where('menu', 1)
                ->where('status', 1)
                ->find();
                
            if (empty($menu)) {
                return json(['code' => 404, 'msg' => '菜单不存在或已禁用']);
            }
            
            // 如果已经有mig_src值，验证是否需要更新
            if (!empty($menu['mig_src'])) {
                // 检查是否需要验证mig_src的有效性
                $currentApiUrl = $menu['mig_src'];
                
                // 如果当前mig_src已经是有效的API格式，则不更新
                if (strpos($currentApiUrl, '/api/v1/') === 0) {
                    return json([
                        'code' => 0,
                        'msg' => '菜单mig_src字段已存在且格式正确',
                        'data' => [
                            'id' => $menu['id'],
                            'mig_src' => $currentApiUrl
                        ]
                    ]);
                }
                
                // 如果mig_src格式不正确，则继续更新流程
            }
            
            // 解析原始src字段
            $src = $menu['src'];
            if (empty($src)) {
                return json(['code' => 400, 'msg' => '菜单src字段为空']);
            }
            
            // 根据src生成对应的API地址
            $apiUrl = $this->convertSrcToApi($src);
            
            if (empty($apiUrl)) {
                return json(['code' => 400, 'msg' => '无法解析src字段为有效的API地址']);
            }
            
            // 验证生成的API地址格式
            if (strpos($apiUrl, '/api/v1/') !== 0) {
                return json(['code' => 400, 'msg' => '生成的API地址格式不正确']);
            }
            
            // 更新数据库，添加更多字段确保数据完整性
            Db::name('admin_rule')
                ->where('id', $menu['id'])
                ->update([
                    'mig_src' => $apiUrl,
                    'update_time' => time()
                ]);
                
            return json([
                'code' => 0,
                'msg' => '成功更新菜单mig_src字段',
                'data' => [
                    'id' => $menu['id'],
                    'src' => $src,
                    'mig_src' => $apiUrl
                ]
            ]);
            
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '更新失败: ' . $e->getMessage()]);
        }
    }

    /**
     * 批量更新菜单的mig_src字段
     */
    public function batchUpdateMigSrc()
    {
        // 直接通过SQL更新所有菜单项的mig_src字段
        // 将src字段中的内容转换为API地址格式并存储到mig_src
        
        // 处理类似 index.php?m=home&c=conf&a=index 的URL
        Db::execute("UPDATE oa_admin_rule SET mig_src = CONCAT('/api/v1/', SUBSTRING_INDEX(SUBSTRING_INDEX(src, 'm=', -1), '&', 1), '/', SUBSTRING_INDEX(SUBSTRING_INDEX(src, 'c=', -1), '&', 1), '/', SUBSTRING_INDEX(SUBSTRING_INDEX(src, 'a=', -1), '&', 1)) WHERE src LIKE '%index.php?m=%' AND src LIKE '%c=%' AND src LIKE '%a=%' AND menu=1 AND status=1");

        // 处理类似 /home/conf/index 的URL
        Db::execute("UPDATE oa_admin_rule SET mig_src = CONCAT('/api/v1/', src) WHERE src LIKE '/%/%/%' AND src NOT LIKE '%index.php%' AND menu=1 AND status=1");

        return json([
            'code' => 0,
            'msg' => '批量更新完成',
            'data' => []
        ]);
    }

    /**
     * 生成树形结构
    /**
     * 更新菜单的mig_src字段，将原系统URL映射为新系统API地址
     */
    public function updateMigSrc()
    {
        // 获取所有菜单项
        $menus = Db::name('admin_rule')
            ->where('menu', 1)
            ->where('status', 1)
            ->select()
            ->toArray();

        $updatedCount = 0;
        foreach ($menus as $menu) {
            // 如果已经有mig_src值，则跳过
            if (!empty($menu['mig_src'])) {
                continue;
            }

            // 解析原始src字段
            $src = $menu['src'];
            if (empty($src)) {
                continue;
            }

            // 根据src生成对应的API地址
            $apiUrl = $this->convertSrcToApi($src);
            
            if (!empty($apiUrl)) {
                // 更新数据库
                Db::name('admin_rule')
                    ->where('id', $menu['id'])
                    ->update([
                        'mig_src' => $apiUrl,
                        'update_time' => time()
                    ]);
                $updatedCount++;
            }
        }

        return json([
            'code' => 0,
            'msg' => '成功更新' . $updatedCount . '条菜单记录',
            'data' => [
                'updated_count' => $updatedCount
            ]
        ]);
    }

    /**
     * 将原系统URL转换为新系统API地址
     * @param string $src 原系统URL
     * @return string API地址
     */
    private function convertSrcToApi($src)
    {
        // 解析原始URL
        if (strpos($src, 'index.php?') !== false) {
            // 处理类似 index.php?m=home&c=conf&a=index 的URL
            parse_str(parse_url($src, PHP_URL_QUERY), $params);
            $module = $params['m'] ?? '';
            $controller = $params['c'] ?? '';
            $action = $params['a'] ?? '';
            
            // 构建API地址
            if ($module && $controller && $action) {
                // 例如: /api/v1/home/conf/index
                return '/api/v1/' . $module . '/' . $controller . '/' . $action;
            }
        } else if (strpos($src, '/') === 0) {
            // 处理类似 /home/conf/index 的URL
            $parts = explode('/', trim($src, '/'));
            if (count($parts) >= 3) {
                // 例如: /api/v1/home/conf/index
                return '/api/v1/' . $parts[0] . '/' . $parts[1] . '/' . $parts[2];
            }
        }

        // 默认返回空，表示未找到对应关系
        return '';
    }

    /**
     * 获取带mig_src字段的菜单树（用于前端展示）
     */
    public function getMenuTree()
    {
        // 获取所有启用的菜单项
        $menuList = Db::name('admin_rule')
            ->where([
                ['menu', '=', 1],
                ['status', '=', 1]
            ])
            ->order('sort asc, id asc')
            ->select()
            ->toArray();

        // 构建树形结构
        $menuTree = $this->buildMenuTree($menuList);
        
        return json([
            'code' => 0,
            'msg' => 'success',
            'data' => $menuTree
        ]);
    }

    /**
     * 构建菜单树
     */
    private function buildMenuTree($menu, $parentId = 0)
    {
        $tree = [];
        if (!is_array($menu)) {
            return $tree;
        }
        
        foreach ($menu as $item) {
            if (isset($item['pid']) && $item['pid'] == $parentId) {
                $children = $this->buildMenuTree($menu, $item['id']);
                if (!empty($children)) {
                    $item['children'] = $children;
                }
                $tree[] = $item;
            }
        }
        return $tree;
    }

    /**
     * 获取菜单列表
     */
    public function list()
    {
        try {
            // 查询启用的菜单列表
            $menus = Db::name('admin_rule')
                ->field('id, pid, title, icon, mig_src as path, sort, status')
                ->where('status', 1)
                ->where('menu', 1)  // 只获取标记为菜单的节点
                ->order('sort asc, id asc')
                ->select()
                ->toArray();
            
            // 处理菜单数据，添加component和redirect字段
            foreach ($menus as &$menu) {
                // 根据path生成component路径
                if (!empty($menu['path'])) {
                    $menu['component'] = $this->generateComponentFromPath($menu['path']);
                } else {
                    $menu['component'] = 'Index';
                }
                
                // 如果有子菜单，则设置redirect为第一个子菜单的路径
                $menu['redirect'] = '';
            }
            unset($menu); // 释放引用
            
            // 生成树形结构
            $list = $this->generateTree($menus);
            
            // 添加固定的工作台菜单项作为第一个菜单
            $dashboardMenu = array(
                'id' => 0,
                'pid' => 0,
                'title' => '工作台',
                'icon' => 'home',
                'path' => '/home',
                'component' => 'Home',
                'redirect' => '',
                'sort' => 0,
                'status' => 1
            );
            
            // 将工作台菜单插入到列表开头
            array_unshift($list, $dashboardMenu);
            
            return json([
                'code' => 0,
                'msg' => 'success',
                'data' => $list
            ]);
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '查询失败: ' . $e->getMessage()]);
        }
    }

    /**
     * 从路径生成组件名
     */
    private function generateComponentFromPath(string $path): string
    {
        $pathParts = array_filter(explode('/', $path));
        $depth = count($pathParts);
        
        if ($depth >= 2) {
            return ucfirst($pathParts[0]) . ucfirst($pathParts[1]);
        } elseif ($depth === 1) {
            return ucfirst($pathParts[0]);
        }
        
        return 'Index';
    }
    
    /**
     * 生成树形结构
     * @param array $list 节点列表
     * @param int $pid 父节点ID
     * @param int $level 当前层级，顶级为0
     * @return array 树形结构数组
     */
    private function generateTree($list, $pid = 0, $level = 0)
    {
        $tree = [];
        foreach ($list as $item) {
            if ($item['pid'] == $pid) {
                // 添加层级属性
                $item['level'] = $level;
                // 递归获取子节点
                $children = $this->generateTree($list, $item['id'], $level + 1);
                if (!empty($children)) {
                    $item['children'] = $children;
                    // 设置重定向到第一个子菜单
                    if (empty($item['redirect']) && !empty($children[0]['path'])) {
                        $item['redirect'] = $children[0]['path'];
                    }
                }
                // 设置hasChildren属性
                $item['hasChildren'] = !empty($children);
                $tree[] = $item;
            }
        }
        return $tree;
    }
    
    /**
     * 获取菜单节点列表
     */
    public function rule_list()
    {
        try {
            
            // 查询所有菜单节点，不使用分页，确保能获取完整的树形结构
            $list = Db::name('admin_rule')
                ->field('a.*,m.title as module_title')
                ->alias('a')
                ->leftJoin('admin_module m', 'a.module = m.name')
                ->order('a.sort asc,a.id asc')
                ->select()
                ->toArray();
            
            // 格式化时间
            foreach ($list as &$item) {
                $item['create_time'] = date('Y-m-d H:i', $item['create_time']);
            }
            
            // 查询总数
            $count = Db::name('admin_rule')
                ->alias('a')
                ->count();
            
            // 生成树形结构
            $tree = $this->generateTree($list);
            
            return json([
                'code' => 0,
                'msg' => 'success',
                'data' => $tree,
                'count' => $count
            ]);
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '查询失败: ' . $e->getMessage()]);
        }
    }
    
    /**
     * 查看单个菜单节点信息
     */
    public function rule_view()
    {
        $param = Request::param();
        
        if (empty($param['id'])) {
            return json(['code' => 400, 'msg' => '参数错误']);
        }
        
        try {
            $rule = Db::name('admin_rule')
                ->field('a.*,m.title as module_title')
                ->alias('a')
                ->leftJoin('admin_module m', 'a.module = m.name')
                ->where('a.id', $param['id'])
                ->find();
            
            if (empty($rule)) {
                return json(['code' => 404, 'msg' => '菜单节点不存在']);
            }
            
            // 格式化时间
            $rule['create_time'] = date('Y-m-d H:i', $rule['create_time']);
            
            return json([
                'code' => 0,
                'msg' => 'success',
                'data' => $rule
            ]);
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '查询失败: ' . $e->getMessage()]);
        }
    }
    
    /**
     * 新建菜单节点
     */
    public function rule_add()
    {
        $param = Request::param();
        
        // 数据验证
        if (empty($param['title'])) {
            return json(['code' => 400, 'msg' => '节点名称不能为空']);
        }
        
        if (empty($param['src'])) {
            return json(['code' => 400, 'msg' => '节点路径不能为空']);
        }
        
        $data = [
            'pid' => $param['pid'] ?? 0,
            'title' => $param['title'],
            'icon' => $param['icon'] ?? '',
            'src' => preg_replace('# #', '', $param['src']),
            'module' => $param['module'] ?? '',
            'menu' => $param['menu'] ?? 1,
            'sort' => $param['sort'] ?? 0,
            'status' => $param['status'] ?? 1,
            'create_time' => time(),
            'update_time' => time()
        ];
        
        try {
            $ruleId = Db::name('admin_rule')->insertGetId($data);
            
            // 自动为系统所有者管理组分配新增的节点
            $group = Db::name('admin_group')->find(1);
            if (!empty($group)) {
                $newGroup = [
                    'id' => 1,
                    'rules' => $group['rules'] . ',' . $ruleId
                ];
                Db::name('admin_group')->update($newGroup);
            }
            
            // 删除后台节点缓存
            // clear_cache('adminRules');
            
            return json(['code' => 0, 'msg' => '添加成功', 'data' => ['id' => $ruleId]]);
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '添加失败: ' . $e->getMessage()]);
        }
    }
    
    /**
     * 编辑菜单节点
     */
    public function rule_edit()
    {
        $param = Request::param();
        
        // 数据验证
        if (empty($param['id'])) {
            return json(['code' => 400, 'msg' => '参数错误']);
        }
        
        if (empty($param['title'])) {
            return json(['code' => 400, 'msg' => '节点名称不能为空']);
        }
        
        if (empty($param['src'])) {
            return json(['code' => 400, 'msg' => '节点路径不能为空']);
        }
        
        $data = [
            'id' => $param['id'],
            'pid' => $param['pid'] ?? 0,
            'title' => $param['title'],
            'icon' => $param['icon'] ?? '',
            'src' => preg_replace('# #', '', $param['src']),
            'module' => $param['module'] ?? '',
            'menu' => $param['menu'] ?? 1,
            'sort' => $param['sort'] ?? 0,
            'status' => $param['status'] ?? 1,
            'update_time' => time()
        ];
        
        try {
            Db::name('admin_rule')->update($data);
            
            // 删除后台节点缓存
            // clear_cache('adminRules');
            
            return json(['code' => 0, 'msg' => '编辑成功']);
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '编辑失败: ' . $e->getMessage()]);
        }
    }
    
    /**
     * 删除菜单节点
     */
    public function rule_del()
    {
        $param = Request::param();
        
        if (empty($param['id'])) {
            return json(['code' => 400, 'msg' => '参数错误']);
        }
        
        try {
            // 检查是否有子节点
            $count = Db::name('admin_rule')
                ->where(["pid" => $param['id']])
                ->count();
            
            if ($count > 0) {
                return json(['code' => 400, 'msg' => '该节点下还有子节点，无法删除']);
            }
            
            Db::name('admin_rule')
                ->where('id', $param['id'])
                ->delete();
            
            // 删除后台节点缓存
            // clear_cache('adminRules');
            
            return json(['code' => 0, 'msg' => '删除成功']);
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '删除失败: ' . $e->getMessage()]);
        }
    }
}